/**************************************************************************
** Yabet is bloging editor tool that supports many blog's formats. It is very usefull for crossposting, allows easily to
** make posts to your blogs.
**
** Copyright (C) 2010 Valery Konchin <eeexception@gmail.com>
**
** This program is free software: you can redistribute it and/or modify
**     it under the terms of the GNU General Public License as published by
**     the Free Software Foundation, either version 3 of the License, or
**     (at your option) any later version.
**
**     This program is distributed in the hope that it will be useful,
**     but WITHOUT ANY WARRANTY; without even the implied warranty of
**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
**     GNU General Public License for more details.
**
**     You should have received a copy of the GNU General Public License
**     along with this program.  If not, see <http://www.gnu.org/licenses/>.
**************************************************************************/

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include <QClipboard>
#include "yabettextmarkup.h"
#include "imageshackimageuploader.h"
#include <QFileDialog>
#include <QMessageBox>

const YabetLogHandler* MainWindow::log = new YabetLogHandler("MainWindow");

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    linkDialog = new LinkDialog(this);
    imageDialog = new ImageDialog(this);
    screenshotDialog = new ScreenshotDialog(this);
    googleTranslateDialog = new GoogleTranslateDialog(this);
    splash = new UploadSplash(this);
    aboutDialog = new AboutDialog(this);

    googleTranslateDialog->setFromLanguages(yabet.getGoogleTranslater()->getLanguagesList());
    googleTranslateDialog->setToLanguages(yabet.getGoogleTranslater()->getLanguagesList());

    yabet.setEditorText(ui->textEdit->document());

    ui->markupsComboBox->addItems(yabet.getMarkupManager()->getMarkupNames());

    ui->toolBar->addAction(ui->actionNew);
    ui->toolBar->addAction(ui->actionOpen);
    ui->toolBar->addAction(ui->actionSave);
    ui->toolBar->addSeparator();

    ui->toolBar->addAction(ui->actionBold);
    ui->toolBar->addAction(ui->actionItalic);
    ui->toolBar->addAction(ui->actionCode);
    ui->toolBar->addAction(ui->actionParagraph);
    ui->toolBar->addAction(ui->actionQuote);
    ui->toolBar->addAction(ui->actionBullet_list);
    ui->toolBar->addSeparator();

    ui->toolBar->addAction(ui->actionLink);
    ui->toolBar->addAction(ui->actionUser_link);
    ui->toolBar->addAction(ui->actionImage);
    ui->toolBar->addAction(ui->actionScreenshot);
    ui->toolBar->addAction(ui->actionSplit_text);
    ui->toolBar->addSeparator();

    ui->toolBar->addAction(ui->actionTranslate);
    ui->toolBar->addAction(ui->actionConvert_html);

    connect(ui->actionBold, SIGNAL(triggered()), this, SLOT(boldAction()));
    connect(ui->actionItalic, SIGNAL(triggered()), this, SLOT(italicAction()));
    connect(ui->actionLink, SIGNAL(triggered()), this, SLOT(insertLinkAction()));
    connect(ui->actionCode, SIGNAL(triggered()), this, SLOT(codeAction()));
    connect(ui->actionSplit_text, SIGNAL(triggered()), this, SLOT(splitTextAction()));
    connect(ui->actionTranslate, SIGNAL(triggered()), this, SLOT(googleTranslateTextButtonPressed()));
    connect(googleTranslateDialog, SIGNAL(accepted()), this, SLOT(googleTranslateDialogAccepted()));

    connect(ui->actionScreenshot, SIGNAL(triggered()), this, SLOT(screenshotButtonPressed()));
    connect(screenshotDialog, SIGNAL(accepted()), this, SLOT(screenshotDialogAccepted()));

    connect(ui->actionBullet_list, SIGNAL(triggered()), this, SLOT(bulletAction()));
    connect(ui->actionParagraph, SIGNAL(triggered()), this, SLOT(paragraphAction()));
    connect(ui->actionQuote, SIGNAL(triggered()), this, SLOT(quoteAction()));
    connect(ui->actionUser_link, SIGNAL(triggered()), this, SLOT(insertUserLinkAction()));

    connect(ui->actionConvert_html, SIGNAL(triggered()), this, SLOT(convertHtmlTagsAction()));

    connect(linkDialog, SIGNAL(acceptedButtonPressed(QString, QString)), this, SLOT(addLinkAcceptedButtonPressed(QString, QString)));

    connect(ui->tabWidget, SIGNAL(currentChanged(int)), this, SLOT(tabChanged(int)));

    connect(ui->markupsComboBox, SIGNAL(currentIndexChanged(QString)), this, SLOT(markupChanged(QString)));

    connect(ui->actionImage, SIGNAL(triggered()), this, SLOT(addImageButtonPressed()));
    connect(imageDialog, SIGNAL(accepted()), this, SLOT(imageDialogAccepted()));

    connect(ui->actionAbout, SIGNAL(triggered()), this, SLOT(aboutDialogShow()));
    connect(ui->actionQuit, SIGNAL(triggered()), this, SLOT(beforeQuit()));
    connect(ui->actionOpen, SIGNAL(triggered()), this, SLOT(openFile()));
    connect(ui->actionSave, SIGNAL(triggered()), this, SLOT(saveFile()));
    connect(ui->actionNew, SIGNAL(triggered()), this, SLOT(newFile()));
    connect(ui->actionSave_as, SIGNAL(triggered()), this, SLOT(saveFileAs()));

    connect(ui->textEdit, SIGNAL(textChanged()), this, SLOT(textChanged()));
    connect(ui->lineEdit, SIGNAL(textChanged(QString)), this, SLOT(textChanged()));

    connect(&yabet, SIGNAL(wasError(QString)), this, SLOT(wasError(QString)));
    connect(&yabet, SIGNAL(wasWarning(QString)), this, SLOT(wasWarning(QString)));

    connect(&yabet, SIGNAL(uploadProgress(qint64,qint64)), splash, SLOT(updateProgressBar(qint64,qint64)));

    newFile();
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::changeEvent(QEvent *e)
{
    QMainWindow::changeEvent(e);
    switch (e->type()) {
    case QEvent::LanguageChange:
        ui->retranslateUi(this);
        break;
    default:
        break;
    }
}

void MainWindow::tabChanged(int index) {
    switch(index) {
    case 1: {
            ui->previewWebView->setHtml(yabet.getText(), ui->previewWebView->url());

            break;
        }
    case 2: {
            ui->copyToTextBrowser->setPlainText(yabet.getText());
            ui->markupsComboBox->setCurrentIndex(ui->markupsComboBox->findText(yabet.getDefaultMarkup()->getMarkupName()));
        }
    default: {
            //No-op
            break;
        }
    }
}

void MainWindow::boldAction() {
    yabet.modifyText(YabetTextMarkup::BOLD_ELEMENT_NAME, ui->textEdit->textCursor().selectionStart(), ui->textEdit->textCursor().selectedText());
}

void MainWindow::italicAction() {
    yabet.modifyText(YabetTextMarkup::ITALIC_ELEMENT_NAME, ui->textEdit->textCursor().selectionStart(), ui->textEdit->textCursor().selectedText());
}

void MainWindow::codeAction() {
    yabet.insertCode(ui->textEdit->textCursor().selectionStart(), ui->textEdit->textCursor().selectedText());
}

void MainWindow::splitTextAction() {
    yabet.modifyText(YabetTextMarkup::TEXT_CUT_ELEMENT_NAME, ui->textEdit->textCursor().selectionStart(), "");
}

void MainWindow::convertHtmlTagsAction() {
    yabet.convertHtmlTags(ui->textEdit->textCursor().selectionStart(), ui->textEdit->textCursor().selectionEnd());
}

void MainWindow::insertLinkAction() {
    linkDialog->setDescription(ui->textEdit->textCursor().selectedText());

    QString clipText = QApplication::clipboard()->text();

    if(clipText.contains("http://") == true || clipText.contains("https://") == true) {
        linkDialog->setUrl(clipText);
    }

    linkDialog->show();
}

void MainWindow::addLinkAcceptedButtonPressed(QString url, QString description) {
    QStringList params;
    params << url << description;

    yabet.modifyText(YabetTextMarkup::LINK_ELEMENT_NAME, ui->textEdit->textCursor().selectionStart(), ui->textEdit->textCursor().selectionEnd(), params);
}

void MainWindow::paragraphAction() {
    yabet.modifyText(YabetTextMarkup::PARAGRAPH_ELEMENT_NAME, ui->textEdit->textCursor().selectionStart(), ui->textEdit->textCursor().selectedText());
}

void MainWindow::quoteAction() {
    yabet.modifyText(YabetTextMarkup::QUOTE_ELEMENT_NAME, ui->textEdit->textCursor().selectionStart(), ui->textEdit->textCursor().selectedText());
}

void MainWindow::insertUserLinkAction() {
    yabet.modifyText(YabetTextMarkup::USER_ELEMENT_NAME, ui->textEdit->textCursor().selectionStart(), ui->textEdit->textCursor().selectedText());
}

void MainWindow::bulletAction() {
    log->debugMsg("Inserting bullets");

    yabet.insertBulletList(ui->textEdit->textCursor().selectionStart(), ui->textEdit->textCursor().selectedText());
}

void MainWindow::markupChanged(QString text) {
    log->debugMsg("Recieved: " + text);

    YabetTextMarkup *markup = yabet.getMarkupManager()->getMarkup(text);
    log->debugMsg("Found: " + markup->getMarkupName());

    QString convertedText = yabet.getMarkupManager()->convertText(yabet.getText(), yabet.getDefaultMarkup(), markup);
    ui->copyToTextBrowser->setPlainText(convertedText);
}

void MainWindow::googleTranslateTextButtonPressed() {
    googleTranslateDialog->show();
}

void MainWindow::googleTranslateDialogAccepted() {
    int startPosition = ui->textEdit->textCursor().selectionStart();

    yabet.translateText(ui->textEdit->textCursor().selectedText(),
                        googleTranslateDialog->getFromLanguage(), googleTranslateDialog->getToLanguage(), startPosition);
}

void MainWindow::addImageButtonPressed() {
    imageDialog->show();
}

void MainWindow::imageDialogAccepted() {
    QString imageFile = imageDialog->getImageFileName();

    splash->startShow();

    QString url = yabet.uploadImage(imageFile, ImageShackImageUploader::IMAGESHACK_IMAGE_HOST);

    log->debugMsg("Recieved url " + url);

    splash->stopShow();

    yabet.modifyText(YabetTextMarkup::IMAGE_ELEMENT_NAME, ui->textEdit->textCursor().selectionStart(), ui->textEdit->textCursor().selectionStart(), QStringList(url));
}

void MainWindow::screenshotButtonPressed() {
    screenshotDialog->show();
}

void MainWindow::screenshotDialogAccepted() {
    QString imageFile = screenshotDialog->getTmpImage();

    splash->startShow();

    QString url = yabet.uploadImage(imageFile, ImageShackImageUploader::IMAGESHACK_IMAGE_HOST);

    log->debugMsg("Recieved url " + url);

    splash->stopShow();

    yabet.modifyText(YabetTextMarkup::IMAGE_ELEMENT_NAME, ui->textEdit->textCursor().selectionStart(), ui->textEdit->textCursor().selectionStart(), QStringList(url));
}

void MainWindow::aboutDialogShow() {
    aboutDialog->show();
}

void MainWindow::openFile() {
    QString filename = QFileDialog::getOpenFileName(this, "Open yabet file", QDir::homePath(), "Yabet file *.ybt (*.ybt)");
    yabet.openFile(filename);

    ui->lineEdit->setText(yabet.getTopic());

    ui->statusBar->showMessage(yabet.getFilename());
}

void MainWindow::saveFile() {
    yabet.setTopic(ui->lineEdit->text());

    if(yabet.getFilename().isEmpty() == true) {
        QString filename = QFileDialog::getSaveFileName(this, "Save yabet file", QDir::homePath(), "Yabet file *.ybt (*.ybt)");

        yabet.setFilename(filename);
    }

    yabet.saveFile(yabet.getFilename());

    yabet.change(false);
    ui->statusBar->showMessage(yabet.getFilename());
}

void MainWindow::saveFileAs() {
    yabet.setTopic(ui->lineEdit->text());

    QString filename = QFileDialog::getSaveFileName(this, "Save yabet file", QDir::homePath(), "Yabet file *.ybt (*.ybt)");

    yabet.saveFile(filename);

    yabet.change(false);
    ui->statusBar->showMessage(yabet.getFilename());
}

void MainWindow::newFile() {
    if(yabet.isChanged() == true) {
        int responseCode = QMessageBox::warning(this, "Unsaved document", "Are really want to create new file with unsaved document?", QMessageBox::Yes | QMessageBox::No);

        if(responseCode == QMessageBox::No) {
            return;
        }
    }

    ui->lineEdit->clear();
    yabet.newFile();

    yabet.change(true);

    ui->statusBar->showMessage("unsaved*");
}

void MainWindow::textChanged() {
    log->debugMsg("Text changed: \n" + ui->textEdit->toHtml());
    if(yabet.getFilename().isEmpty() == false) {
        ui->statusBar->showMessage(yabet.getFilename() + " *changed");
    }

    yabet.change(true);
}

void MainWindow::beforeQuit() {
    if(yabet.isChanged() == true) {
        int responseCode = QMessageBox::warning(this, "Unsaved document", "Are really want to quit with unsaved document?", QMessageBox::Yes | QMessageBox::No);

        if(responseCode == QMessageBox::No) {
            return;
        }
    }

    emit quitGui();
}

void MainWindow::wasError(QString msg) {
    QMessageBox::critical(this, "Critical error", msg, QMessageBox::Ok);
}

void MainWindow::wasWarning(QString msg) {
    QMessageBox::warning(this, "Warning", msg, QMessageBox::Ok);
}
